#include "comm/znx_queue.h"

typedef struct {
    int         a;
    znx_queue_t  queue;
} test_obj_t;

void test_queue() {
    test_obj_t a1 = {.a = 1};
    test_obj_t a2 = {.a = 2};
    test_obj_t a3 = {.a = 3};
    test_obj_t a4 = {.a = 4};
    test_obj_t a5 = {.a = 5};

    znx_queue_t queue_a;
    znx_queue_init(&queue_a);
    znx_queue_insert_head(&queue_a, &a1.queue);
    znx_queue_insert_head(&queue_a, &a2.queue);
    znx_queue_insert_head(&queue_a, &a3.queue);
    znx_queue_insert_head(&queue_a, &a4.queue);
    znx_queue_insert_head(&queue_a, &a5.queue);

    znx_queue_t *last;
    test_obj_t *data;
    int  i = 1;
    while(!znx_queue_empty(&queue_a)) {
        last = znx_queue_last(&queue_a);
        znx_queue_remove(last);
        data = znx_queue_data(last, test_obj_t, queue);
        assert(data->a == i);
        i++;
    }

    znx_queue_insert_tail(&queue_a, &a1.queue);
    znx_queue_insert_tail(&queue_a, &a2.queue);
    znx_queue_insert_tail(&queue_a, &a3.queue);
    znx_queue_insert_tail(&queue_a, &a4.queue);
    znx_queue_insert_tail(&queue_a, &a5.queue);

    znx_queue_t *head;
    i = 1;
    while(!znx_queue_empty(&queue_a)) {
        head = znx_queue_head(&queue_a);
        znx_queue_remove(head);
        data = znx_queue_data(head, test_obj_t, queue);
        assert(data->a == i);
        i++;
    }
}

void test_queue_move() {
    test_obj_t a1 = {.a = 1};
    test_obj_t a2 = {.a = 2};
    test_obj_t a3 = {.a = 3};
    test_obj_t a4 = {.a = 4};
    test_obj_t a5 = {.a = 5};

    znx_queue_t queue_a;
    znx_queue_init(&queue_a);
    znx_queue_insert_head(&queue_a, &a1.queue);
    znx_queue_insert_head(&queue_a, &a2.queue);
    znx_queue_insert_head(&queue_a, &a3.queue);
    znx_queue_insert_head(&queue_a, &a4.queue);
    znx_queue_insert_head(&queue_a, &a5.queue);

    test_obj_t b1 = {.a = 11};
    test_obj_t b2 = {.a = 12};
    test_obj_t b3 = {.a = 13};
    test_obj_t b4 = {.a = 14};
    test_obj_t b5 = {.a = 15};

    znx_queue_t queue_b;
    znx_queue_init(&queue_b);
    znx_queue_insert_head(&queue_b, &b1.queue);
    znx_queue_insert_head(&queue_b, &b2.queue);
    znx_queue_insert_head(&queue_b, &b3.queue);
    znx_queue_insert_head(&queue_b, &b4.queue);
    znx_queue_insert_head(&queue_b, &b5.queue);

    znx_queue_move(&queue_a, &queue_b);

    assert(znx_queue_empty(&queue_a));

    znx_queue_t *last;
    test_obj_t *data;
    int i = 11;
    while(!znx_queue_empty(&queue_b)) {
        last = znx_queue_last(&queue_b);
        znx_queue_remove(last);
        data = znx_queue_data(last, test_obj_t, queue);
        assert(data->a == i);

        i++;
        if (i == 16) {
            i = 1;
        }
    }
}

void test_queue_move_to_empty_queue() {
    test_obj_t a1 = {.a = 1};
    test_obj_t a2 = {.a = 2};
    test_obj_t a3 = {.a = 3};
    test_obj_t a4 = {.a = 4};
    test_obj_t a5 = {.a = 5};

    znx_queue_t queue_a;
    znx_queue_init(&queue_a);
    znx_queue_insert_head(&queue_a, &a1.queue);
    znx_queue_insert_head(&queue_a, &a2.queue);
    znx_queue_insert_head(&queue_a, &a3.queue);
    znx_queue_insert_head(&queue_a, &a4.queue);
    znx_queue_insert_head(&queue_a, &a5.queue);

    znx_queue_t queue_b;
    znx_queue_init(&queue_b);
    znx_queue_move(&queue_a, &queue_b);

    znx_queue_t *last;
    test_obj_t *data;
    int i = 1;
    while(!znx_queue_empty(&queue_b)) {
        last = znx_queue_last(&queue_b);
        znx_queue_remove(last);
        data = znx_queue_data(last, test_obj_t, queue);
        assert(data->a == i);

        i++;
    }

}

int main() {
    test_queue();
    test_queue_move();
    test_queue_move_to_empty_queue();
    return 0;
}
